#!/usr/bin/perl -w
use strict;
use v5.14;
use utf8;

use Data::Dumper;
use Encode;
use Net::LDAP;
use Config::Simple;
binmode(STDOUT, ":encoding(UTF-8)");
binmode(STDIN, ":encoding(UTF-8)");
binmode(STDERR, ":encoding(UTF-8)");

sub gen_uid_number {
  my $conn = shift @_;
  my $uid_number = 0;
  my $msg = $conn->search(base => 'cn=max_uid_number,dc=jhc,dc=cn',
			  scope => 'base',
			  filter => '(objectClass=*)',
			  callback => sub {
			    my ($result,$entry) = @_;
			    $result->code && say $result->error;
			    if ($entry) {
			      $uid_number = $entry->get_value('uidNumber');
			      $entry->replace(uidNumber => $uid_number+1);
			      $entry->update($conn);
			    }
			  }
			 );
  $uid_number;
}

my $USAGE = "用法： ./add_user.pl 学号 姓名 班级名 学院名";
(@ARGV < 3 || @ARGV > 4) && die $USAGE;
my ($uid,$name,$classname,$institute) = @ARGV;
$institute || ($institute = 'info');
#say $classname . ',' . $institute;

my $cfg = new Config::Simple($ENV{'HOME'} . '/.ldapconf');
#$cfg->param('binddn');
my $ldap = Net::LDAP->new($cfg->param('host'));
$ldap->bind($cfg->param('binddn'), password => $cfg->param('password'));

#根据班级名找出班级的group entry
my $groupentry;
my $groupdn = "cn=" . decode("utf8",$classname) . ",ou=${institute},ou=groups,dc=jhc,dc=cn";
$ldap->search(base => $groupdn,
	      scope => 'base',
	      filter => '(objectClass=posixGroup)',
	      callback => sub{
		my ($result,$entry) = @_;
		$result->code && warn $result->error;
		if ($entry) {
		  $groupentry = $entry;
		}
	      }
	     );
#say Dumper($groupentry);
$groupentry || die "can find group entry $groupdn.";

#生成最新uidNumber，添加用户
my $uidnum = gen_uid_number($ldap);
#say $uidnum;
#抽取姓和名，姓为第一个汉字
my $sn = substr(decode('utf8',$name), 0, 1);
my $gn = substr(decode('utf8',$name), 1);
my $userdn = "uid=${uid},ou=${institute},ou=people,dc=jhc,dc=cn";
my $addmsg = $ldap->add($userdn,
			attrs => [
				  cn => $name,
				  sn => $sn,
				  gn => $gn,
				  uid => $uid,
				  homeDirectory => '/nonexistent',
				  uidNumber => $uidnum,
				  gidNumber => $groupentry->get_value('gidNumber'),
				  userPassword => $uid,
				  objectClass => [qw/top person organizationalPerson inetOrgPerson posixAccount/]
				 ]
		       );
$addmsg->code && say "Failed to add user: " . $userdn, $addmsg->error && exit 1;

#将用户加到group
$groupentry->add(memberUid => [$uid])->update($ldap);
say "dn:${userdn} is added.";
$ldap->unbind;

